#!/usr/bin/perl -w 

# 16 CUDA benchmarks, Inti, 100 hrs max
# 13 rodinia benchmarks, Titan, 200 hrs max
# 7  parboil benchmarks, Inti, 200 hrs max

use English;

@cuda = ("AES", "BFS", "BlackScholes", "CP", "JPEG", "kmeans", "LIB", "LPS", "MUM", "NN", "NQU", "RAY", "STO", "WP", "denoise", "SAD");

@rodinia = ("backprop", "bfs", "hotspot", "heartwall", "cfd", "streamcluster", "nw", "lud", "leukocyte", "pf_float", "pf_naive", "srad_v1", "srad_v2");

@parboil = ("cutcp", "fft", "lbm", "mm", "sad", "spmv", "tpacf");

@cuda_list = ("CUDA/AES/output_AES.txt", 
"CUDA/BFS/output_BFS.txt", "CUDA/BlackScholes/output_BlackScholes.txt", "CUDA/CP/output_CP.txt","CUDA/JPEG/output_JPEG.txt", "CUDA/kmeans/output_kmeans.txt","CUDA/LIB/output_LIB.txt", "CUDA/LPS/output_LPS.txt", "CUDA/MUM/output_MUM.txt", "CUDA/NN/output_NN.txt", "CUDA/NQU/output_NQU.txt", "CUDA/RAY/output_RAY.txt", "CUDA/STO/output_STO.txt", "CUDA/WP/output_WP.txt", "CUDA/denoise/output_denoise.txt","CUDA/SAD/output_SAD.txt");


@rodinia_list = ("rodinia/backprop/output_backprop.txt", "rodinia/bfs/output_bfs.txt", "rodinia/hotspot/output_hotspot.txt", "rodinia/heartwall/output_heartwall.txt", "rodinia/cfd/output_cfd.txt", "rodinia/streamcluster/output_streamcluster.txt", "rodinia/nw/output_nw.txt", 
"rodinia/lud/output_lud.txt", "rodinia/leukocyte/output_leukocyte.txt", "rodinia/pf_float/output_pf_float.txt", 
"rodinia/pf_naive/output_pf_naive.txt", "rodinia/srad_v1/output_srad_v1.txt", "rodinia/srad_v2/output_srad_v2.txt");


@parboil_list = ("parboil/cutcp/output_cutcp.txt", "parboil/fft/output_fft.txt", "parboil/lbm/output_lbm.txt",
"parboil/mm/output_mm.txt", "parboil/sad/output_sad.txt", "parboil/spmv/output_spmv.txt", "parboil/tpacf/output_tpacf.txt");

print "$ARGV[0]\n";

$bench = $ARGV[0];

if ($bench eq "CUDA") {
@file_list = @cuda_list;
@benchmarks = @cuda;
$result_file = "CUDA_results.txt";
}

if ($bench eq "rodinia") {
@file_list = @rodinia_list;
@benchmarks = @rodinia;
$result_file = "rodinia_results.txt";
}

if ($bench eq "parboil") {
@file_list = @parboil_list;
@benchmarks = @parboil;
$result_file = "parboil_results.txt";
}

if ($bench eq "ALL") {
@file_list = (@cuda_list, @rodinia_list, @parboil_list);
@benchmarks = (@cuda, @rodinia, @parboil);
$result_file = "all_results.txt";
}


open(OUTPUT, ">$result_file") || die "Cannot open file $result_file for writing\n";

for ($j = 0; $j <= $#file_list; $j++) {  

    my $latency = `grep "average latency" $file_list[$j] | tail -n 1 | awk '\{print \$5\}'`;
	chomp($latency);
	push @globallatency, $latency;
	
	my $ipc = `grep gpu_tot_ipc $file_list[$j] | tail -n 1 | awk '\{print \$3\}'`;
	chomp($ipc);
	push @globalipc, $ipc;
	
	my $ins = `grep gpu_tot_sim_insn $file_list[$j] | tail -n 1 | awk '\{print \$3\}'`;
	chomp($ins);
	push @globalins, $ins;	
	
	my $total_demand_RL = `grep \"gpgpu_n_mem_read_local =\" $file_list[$j] | tail -n 1 | awk '\{print \$3\}'`;
        chomp($total_demand_RL);

	my $total_demand_RG = `grep \"gpgpu_n_mem_read_global =\" $file_list[$j] | tail -n 1 | awk '\{print \$3\}'`;
	chomp($total_demand_RG);
	
	push @globaldemand_rgl, ($total_demand_RL + $total_demand_RG);
	
        my $L1readhit = `grep  "L1 read hit" $file_list[$j] | tail -n  1 | awk '\{print \$5\}'`;
	chomp($L1readhit);
	
	my $L1readmiss = `grep  "L1 read misses" $file_list[$j] | tail -n  1 | awk '\{print \$5\}'`;
	chomp($L1readmiss);
	push @globalL1readmiss, $L1readmiss;

    push @globalL1missrate, ($L1readmiss)/($L1readhit + $L1readmiss); #NOT IMP
	
        my $L2readhit = `grep  "L2_read_hit" $file_list[$j] | tail -n  1 | awk '\{print \$3\}'`;
	chomp($L2readhit);
	
	my $L2readmiss = `grep  "L2_read_miss" $file_list[$j] | tail -n  1 | awk '\{print \$3\}'`;
	chomp($L2readmiss);

	push @globalL2missrate, ($L2readmiss)/($L2readhit + $L2readmiss);

	
	my $Stall = `grep "Stall" $file_list[$j] | tail -n 1 |  awk -F ':' '\{print \$2\}' |  awk '\{print \$1\}'`;
	chomp($Stall);
	push @globalStall, $Stall;
	
	my $W0Idle= `grep "Stall" $file_list[$j] | tail -n 1 |  awk -F ':' '\{print \$3\}' |  awk '\{print \$1\}'`;
	chomp($W0Idle);
	push @globalW0Idle, $W0Idle;
	
	my $W0Mem = `grep "Stall" $file_list[$j] | tail -n 1 |  awk -F ':' '\{print \$4\}' |  awk '\{print \$1\}'`;
	chomp($W0Mem);
	push @globalW0Mem, $W0Mem;
	
	my $net_throughput = `grep "average accepted rate" $file_list[$j] | tail -n 1 |  awk '\{print \$6\}'`;
    chomp($net_throughput);
    push @globalnet_throughput, $net_throughput;
	
	my $net_lat = `grep "gpgpu_network_latency" $file_list[$j] | tail -n 1 |  awk '\{print \$3\}'`;
    chomp($net_lat);
    push @globalnet_lat, $net_lat;
	
	@dram_eff = `grep "dram_eff=" $file_list[$j] | tail -n 8 |  awk '\{print \$2\}' |  awk -F '=' '\{print \$2\}'`;
	chomp(@dram_eff);
	push @globaldram_eff, [avg(\@dram_eff)];
	
	@dram_util = `grep "bw_util" $file_list[$j] | tail -n 8 |  awk '\{print \$8\}' |  awk -F '=' '\{print \$2\}'`;
	chomp(@dram_util);
	push @globaldram_util, [avg(\@dram_util)];
	
	my $maxmrqlatency = `grep "maxmrqlatency" $file_list[$j] | tail -n 1 |  awk '\{print \$3\}'`;
	chomp($maxmrqlatency);
    push @globalmaxmrqlatency, $maxmrqlatency;

	my $averagemflatency = `grep "averagemflatency" $file_list[$j] | tail -n 1 |  awk '\{print \$3\}'`;
	chomp($averagemflatency);
    push @globalaveragemflatency, $averagemflatency;
	
	
	my $prefetch_rg = `grep gpgpu_prefetch_init $file_list[$j] | tail -n 1 | awk '\{print \$3\}'`;
	chomp($prefetch_rg);

	push @total_prefetch, ($prefetch_rg);
	

	my $prefetch_demand = `grep gpgpu_demand_init $file_list[$j] | tail -n 1 | awk '\{print \$3\}'`;
	chomp($prefetch_demand);
	push @globalprefetch_demand, $prefetch_demand;
	
	push @totalrequests, ($prefetch_rg + $prefetch_rl + $prefetch_demand);
   
 
	
	@L1accuracy = `grep gpgpu_prefetch_L1_accuracy $file_list[$j] | awk '\{print \$3\}'`;
	chomp(@L1accuracy);
	push @globalL1accuracy, [max(\@L1accuracy)];
	
	@L2accuracy = `grep gpgpu_prefetch_L2_accuracy $file_list[$j] | awk '\{print \$3\}'`;
	chomp(@L2accuracy);
	push @globalL2accuracy, [max(\@L2accuracy)];
	
	my $prefetch_late = `grep gpgpu_prefetch_late $file_list[$j] | tail -n 1 | awk '\{print \$3\}'`;
	chomp($prefetch_late);
	push @globalprefetch_late, $prefetch_late;
	
	my $prefetch_cancelled = `grep gpgpu_prefetch_cancelled $file_list[$j] | tail -n 1 | awk '\{print \$3\}'`;
	chomp($prefetch_cancelled);
	push @globalprefetch_cancelled, $prefetch_cancelled;
	
	my $L1prefetchinit = `grep gpgpu_prefetch_L1_init $file_list[$j] | tail -n 1 | awk '\{print \$3\}'`;
	chomp($L1prefetchinit);
	push @globalL1prefetchinit, $L1prefetchinit;

	my $L2prefetchinit = `grep gpgpu_prefetch_L2_init $file_list[$j] | tail -n 1 | awk '\{print \$3\}'`;
	chomp($L2prefetchinit);
	push @globalL2prefetchinit, $L2prefetchinit;

	my $L1prefetchuseful = `grep gpgpu_prefetch_L1_useful $file_list[$j] | tail -n 1 | awk '\{print \$3\}'`;
	chomp($L1prefetchuseful);
	push @globalL1prefetchuseful, $L1prefetchuseful;

	my $L2prefetchuseful = `grep gpgpu_prefetch_L2_useful $file_list[$j] | tail -n 1 | awk '\{print \$3\}'`;
	chomp($L2prefetchuseful);
	push @globalL2prefetchuseful, $L2prefetchuseful;
	
 } 
    # BASELINE Starts ----------------------------------------------------------------
 	# General ----------------------------------
	print OUTPUT "Benchmarks \t";
	print OUTPUT "latency \t";
	print OUTPUT "IPC\t";
	print OUTPUT "INS\t";
	print OUTPUT "Dem-RGL\t";  # Initial Demands 
	
	
	# Cache Related ----------------------------
	print OUTPUT "L1 R-M \t";
	print OUTPUT "L2 R-MR \t";
	
	# Warp Related -----------------------------
	print OUTPUT "Stall \t";
	print OUTPUT "W0Idle \t";
	print OUTPUT "W0Mem \t";
    # Add for Distribution -- Branch Divergence
	
	# Network Related --------------------------
	print OUTPUT "net-thru \t";
	print OUTPUT "net-lat-me\t";
	
	# DRAM Related -----------------------------
	print OUTPUT "DRAM-eff \t";
	print OUTPUT "DRAM-util \t";
	print OUTPUT "Queue-lat \t";
	print OUTPUT "avg-mem-latency \t";

	# BASELINE Over ----------------------------------------------------------------
	
	
	# Prefetch Related -------------------------

	print OUTPUT "tot-Pre \t"; # total prefetches sent
	print OUTPUT "tot-Dem \t"; # total demands sent
	print OUTPUT "tot-req \t"; # total requests in the network
	
	print OUTPUT "L1 Accuracy \t";
	print OUTPUT "L2 Accuracy \t";
	print OUTPUT "p_late \t";
	print OUTPUT "p_cancel \t";

	print OUTPUT "L1 init \t";
	print OUTPUT "L2 init \t";
	print OUTPUT "L1 useful \t";
	print OUTPUT "L2 useful \t";

	
	print OUTPUT "\n";


for ($k = 0;$k <= $#file_list;$k++) 
{
    # BASELINE Starts ----------------------------------------------------------------
 	# General ----------------------------------
	print OUTPUT "$benchmarks[$k] \t";
	print OUTPUT "$globallatency[$k] \t";
	print OUTPUT "$globalipc[$k] \t";
	print OUTPUT "$globalins[$k] \t";
	print OUTPUT "$globaldemand_rgl[$k] \t";

	# Cache Related ----------------------------
	print OUTPUT "$globalL1readmiss[$k] \t";
	print OUTPUT "$globalL2missrate[$k] \t";
	
	# Warp Related -----------------------------
	print OUTPUT "$globalStall[$k] \t";
	print OUTPUT "$globalW0Idle[$k] \t";
	print OUTPUT "$globalW0Mem[$k] \t";
    # Add for Distribution -- Branch Divergence
	
	# Network Related --------------------------
	print OUTPUT "$globalnet_throughput[$k] \t";
	print OUTPUT "$globalnet_lat[$k] \t";
	
	# DRAM Related -----------------------------
	print OUTPUT "$globaldram_eff[$k][0] \t";
	print OUTPUT "$globaldram_util[$k][0] \t";
	print OUTPUT "$globalmaxmrqlatency[$k] \t";
	print OUTPUT "$globalaveragemflatency[$k] \t";
	# BASELINE Over ----------------------------------------------------------------
	
	
	# Prefetch Related -------------------------
	print OUTPUT "$total_prefetch[$k] \t"; # 1
	print OUTPUT "$globalprefetch_demand[$k] \t"; # 2
	print OUTPUT "$totalrequests[$k] \t"; # 1 + 2

	
	print OUTPUT "$globalL1accuracy[$k][0] \t";
	print OUTPUT "$globalL2accuracy[$k][0] \t";
	print OUTPUT "$globalprefetch_late[$k] \t";
	print OUTPUT "$globalprefetch_cancelled[$k] \t";
	print OUTPUT "$globalL1prefetchinit[$k] \t";
	print OUTPUT "$globalL2prefetchinit[$k] \t";
	print OUTPUT "$globalL1prefetchuseful[$k] \t";
	print OUTPUT "$globalL2prefetchuseful[$k] \t";

	print OUTPUT "\n";
}


sub avg {
	@_ == 1 or die ('Sub usage: $avg = avg(\@array);');
	my ($array_ref) = @_;
	my $sum;
	my $count = scalar @$array_ref;
        if ($count == 0) {
                return 0;
        }
	foreach (@$array_ref) { $sum += $_; }
	return $sum / $count;
}

sub max {
	@_ == 1 or die ('Sub usage: $max = max(\@array);');
	my ($array_ref) = @_;
	my $maxval = -999999999999999999;
	foreach (@$array_ref)
	{
		if ( $maxval < $_ )
		{
			$maxval = $_;
		}
	}
	return $maxval;
}

sub sum {
	@_ == 1 or die ('Sub usage: $sum = sum(\@array);');
	my ($array_ref) = @_;
	my $sum;
	foreach (@$array_ref) { $sum += $_; }
	return $sum;
}


	# my $L1accuracy_last = `grep gpgpu_prefetch_L1_accuracy $file_list[$j] | tail -n 1 | awk '\{print \$3\}'`;
	# chomp($L1accuracy_last);
	# push @globalL1accuracy_last, $L1accuracy_last;
	
	# my $L2accuracy_last = `grep gpgpu_prefetch_L2_accuracy $file_list[$j] | tail -n 1 | awk '\{print \$3\}'`;
	# chomp($L2accuracy_last);
	# push @globalL2accuracy_last, $L2accuracy_last;



